From: Tim Deegan Date: Thu, 18 Jan 2007 16:48:07 +0000 (+0000) Subject: [HVM] save restore: device model support X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15371^2~133^2~9^2~10 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/%22/%22http:/www.example.com/cgi/%22?a=commitdiff_plain;h=9a3e4bbea42f8b524684e8dbeff02115fa4b476a;p=xen.git [HVM] save restore: device model support Signed-off-by: Zhai Edwin qemu's save/restore including vga acceleration support --- diff --git a/tools/ioemu/hw/cirrus_vga.c b/tools/ioemu/hw/cirrus_vga.c index 4a5631195c..8467b403a9 100644 --- a/tools/ioemu/hw/cirrus_vga.c +++ b/tools/ioemu/hw/cirrus_vga.c @@ -3010,11 +3010,44 @@ static CPUWriteMemoryFunc *cirrus_mmio_write[3] = { cirrus_mmio_writel, }; +void cirrus_stop_acc(CirrusVGAState *s) +{ + if (s->map_addr){ + int error; + s->map_addr = 0; + error = unset_vram_mapping(s->cirrus_lfb_addr, + s->cirrus_lfb_end); + fprintf(stderr, "cirrus_stop_acc:unset_vram_mapping.\n"); + + munmap(s->vram_ptr, VGA_RAM_SIZE); + } +} + +void cirrus_restart_acc(CirrusVGAState *s) +{ + if (s->cirrus_lfb_addr && s->cirrus_lfb_end) { + void *vram_pointer, *old_vram; + fprintf(stderr, "cirrus_vga_load:re-enable vga acc.lfb_addr=0x%lx, lfb_end=0x%lx.\n", + s->cirrus_lfb_addr, s->cirrus_lfb_end); + vram_pointer = set_vram_mapping(s->cirrus_lfb_addr ,s->cirrus_lfb_end); + if (!vram_pointer){ + fprintf(stderr, "cirrus_vga_load:NULL vram_pointer\n"); + } else { + old_vram = vga_update_vram((VGAState *)s, vram_pointer, + VGA_RAM_SIZE); + qemu_free(old_vram); + s->map_addr = s->cirrus_lfb_addr; + s->map_end = s->cirrus_lfb_end; + } + } +} + /* load/save state */ static void cirrus_vga_save(QEMUFile *f, void *opaque) { CirrusVGAState *s = opaque; + uint8_t vga_acc; qemu_put_be32s(f, &s->latch); qemu_put_8s(f, &s->sr_index); @@ -3049,11 +3082,20 @@ static void cirrus_vga_save(QEMUFile *f, void *opaque) qemu_put_be32s(f, &s->hw_cursor_y); /* XXX: we do not save the bitblt state - we assume we do not save the state when the blitter is active */ + + vga_acc = (!!s->map_addr); + qemu_put_8s(f, &vga_acc); + qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_addr); + qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_end); + qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); + if (vga_acc) + cirrus_stop_acc(s); } static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) { CirrusVGAState *s = opaque; + uint8_t vga_acc = 0; if (version_id != 1) return -EINVAL; @@ -3092,6 +3134,14 @@ static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) qemu_get_be32s(f, &s->hw_cursor_x); qemu_get_be32s(f, &s->hw_cursor_y); + qemu_get_8s(f, &vga_acc); + qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_addr); + qemu_get_be64s(f, (uint64_t*)&s->cirrus_lfb_end); + qemu_get_buffer(f, s->vram_ptr, VGA_RAM_SIZE); + if (vga_acc){ + cirrus_restart_acc(s); + } + /* force refresh */ s->graphic_mode = -1; cirrus_update_bank_ptr(s, 0); @@ -3297,6 +3347,8 @@ void pci_cirrus_vga_init(PCIBus *bus, DisplayState *ds, uint8_t *vga_ram_base, ds, vga_ram_base, vga_ram_offset, vga_ram_size); cirrus_init_common(s, device_id, 1); + register_savevm("cirrus_vga_pci", 0, 1, generic_pci_save, generic_pci_load, d); + /* setup memory space */ /* memory #0 LFB */ /* memory #1 memory-mapped I/O */ diff --git a/tools/ioemu/hw/ide.c b/tools/ioemu/hw/ide.c index 532afbbffd..ef203a2f8a 100644 --- a/tools/ioemu/hw/ide.c +++ b/tools/ioemu/hw/ide.c @@ -2512,6 +2512,9 @@ void pci_piix3_ide_init(PCIBus *bus, BlockDriverState **hd_table, int devfn) pic_set_irq_new, isa_pic, 15); ide_init_ioport(&d->ide_if[0], 0x1f0, 0x3f6); ide_init_ioport(&d->ide_if[2], 0x170, 0x376); + + register_savevm("ide_pci", 0, 1, generic_pci_save, generic_pci_load, d); + #ifdef DMA_MULTI_THREAD dma_create_thread(); #endif //DMA_MULTI_THREAD diff --git a/tools/ioemu/hw/pci.c b/tools/ioemu/hw/pci.c index 77737c8615..5882f17ece 100644 --- a/tools/ioemu/hw/pci.c +++ b/tools/ioemu/hw/pci.c @@ -63,6 +63,7 @@ void generic_pci_save(QEMUFile* f, void *opaque) qemu_put_buffer(f, s->config, 256); } +void pci_update_mappings(PCIDevice *d); int generic_pci_load(QEMUFile* f, void *opaque, int version_id) { PCIDevice* s=(PCIDevice*)opaque; @@ -71,6 +72,7 @@ int generic_pci_load(QEMUFile* f, void *opaque, int version_id) return -EINVAL; qemu_get_buffer(f, s->config, 256); + pci_update_mappings(s); return 0; } diff --git a/tools/ioemu/target-i386-dm/helper2.c b/tools/ioemu/target-i386-dm/helper2.c index ae84b9ed23..dc3394d5b7 100644 --- a/tools/ioemu/target-i386-dm/helper2.c +++ b/tools/ioemu/target-i386-dm/helper2.c @@ -546,6 +546,7 @@ int main_loop(void) { extern int vm_running; extern int shutdown_requested; + extern int suspend_requested; CPUState *env = cpu_single_env; int evtchn_fd = xc_evtchn_fd(xce_handle); @@ -563,12 +564,24 @@ int main_loop(void) qemu_system_reset(); reset_requested = 0; } + if (suspend_requested) { + fprintf(logfile, "device model received suspend signal!\n"); + break; + } } /* Wait up to 10 msec. */ main_loop_wait(10); } - destroy_hvm_domain(); + if (!suspend_requested) + destroy_hvm_domain(); + else { + char qemu_file[20]; + sprintf(qemu_file, "/tmp/xen.qemu-dm.%d", domid); + if (qemu_savevm(qemu_file) < 0) + fprintf(stderr, "qemu save fail.\n"); + } + return 0; } diff --git a/tools/ioemu/vl.c b/tools/ioemu/vl.c index 573687a08d..f6cc82335c 100644 --- a/tools/ioemu/vl.c +++ b/tools/ioemu/vl.c @@ -4441,6 +4441,11 @@ int qemu_loadvm(const char *filename) qemu_fseek(f, cur_pos + record_len, SEEK_SET); } fclose(f); + + /* del tmp file */ + if (unlink(filename) == -1) + fprintf(stderr, "delete tmp qemu state file failed.\n"); + ret = 0; the_end: if (saved_vm_running) @@ -5027,6 +5032,7 @@ typedef struct QEMUResetEntry { static QEMUResetEntry *first_reset_entry; int reset_requested; int shutdown_requested; +int suspend_requested; static int powerdown_requested; void qemu_register_reset(QEMUResetHandler *func, void *opaque) @@ -5808,6 +5814,14 @@ int set_mm_mapping(int xc_handle, uint32_t domid, return 0; } +void suspend(int sig) +{ + fprintf(logfile, "suspend sig handler called with requested=%d!\n", suspend_requested); + if (sig != SIGUSR1) + fprintf(logfile, "suspend signal dismatch, get sig=%d!\n", sig); + suspend_requested = 1; +} + #if defined(__i386__) || defined(__x86_64__) static struct map_cache *mapcache_entry; static unsigned long nr_buckets; @@ -6718,6 +6732,26 @@ int main(int argc, char **argv) vm_start(); } } + + /* register signal for the suspend request when save */ + { + struct sigaction act; + sigset_t set; + act.sa_handler = suspend; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + + sigaction(SIGUSR1, &act, NULL); + + /* control panel mask some signals when spawn qemu, need unmask here*/ + sigemptyset(&set); + sigaddset(&set, SIGUSR1); + sigaddset(&set, SIGTERM); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) + fprintf(stderr, "unblock signal fail, possible issue for HVM save!\n"); + + } + main_loop(); quit_timers(); return 0;